package swym.server;

import java.io.*;
import java.net.*;
import java.util.*;

import swym.server.config.*;
import swym.server.events.*;

public class Server extends Thread
{
   /** port number */
    private static final int PORT         = 32000;
    private static final int BACKLOG_SIZE = 16; // arbitrary
    private static final int SOCKET_TIMEOUT = 2000; // two seconds
    
    private volatile boolean continueServing;
    private Vector<ClientConnectionHandler> activeConnections;
    
    private static Vector<ServerListener> listeners = new Vector<ServerListener>();

   /** constructor */
    public Server() 
    {
        continueServing = true;
        activeConnections = new Vector<ClientConnectionHandler>();
    }
    
    public void stopServer()
    {
        continueServing = false;
    }
    
    public static void addListener( ServerListener listener )
    {
        synchronized ( listeners )
        {
            if ( listener != null )
            {
                listeners.add( listener );
            }
            else
                throw new NullPointerException( "null server listener" );
        }
    }
    
    public static void removeListener( ServerListener listener )
    {
        synchronized ( listeners )
        {
            listeners.remove( listener );
        } 
    }
    
    public static void invokeShutdownEvent()
    {
        synchronized ( listeners )
        {
            for ( ServerListener listener : listeners )
                listener.handleShutdown();
        } 
    }

    /** loop */
    public void run()
    {        
        try
        {
            ServerSocket serverSocket = new ServerSocket( PORT, BACKLOG_SIZE );

            Log.writeEntry( "Now serving..." );
            
            serverSocket.setSoTimeout( SOCKET_TIMEOUT );
            
            while( continueServing )
            {
                try
                {
                    Socket clientSocket = serverSocket.accept();
                    
                    ClientConnectionHandler connection = new ClientConnectionHandler( clientSocket ); 
                
                    activeConnections.add( connection );
                    
                    connection.start();
                }
                catch ( SocketTimeoutException e )
                {
                    
                }
            }
            
            // Tell everyone who is listening that the server
            // is shutting down.
            Server.invokeShutdownEvent();
        }
        catch( Exception e )
        {
             System.err.println( e.toString() );
        }
        finally
        {
            // TODO: tell all of the activeConnections to close and wait..
        }
    }
	
    /** start here */
    public static void main( String[] argv )
    {
        Settings.loadSettings();
        
        try 
        {
            SocketOutputThread.getInstance().startThread();
            
            Server server = new Server();
            
            server.start();
            
            BufferedReader br = new BufferedReader( new InputStreamReader( System.in ) );
            
            System.out.println( "To stop, use CTRL-d on Unix/Linux, CTRL-z on Windows." );
            
            int input = 0;
            
            while ( input != -1 && input != 113 )
            {
                if ( input == 115 ) // 's'
                    UserManager.getInstance().printStatus();
                
                input = System.in.read();
            }
            
            server.stopServer();
            
            server.join();
            
            System.out.println( "done" );
        }
        catch( Exception e )
        {
             System.err.println( e.toString() );
        }
        
        SocketOutputThread.getInstance().stopThread();
        
        Settings.writeSettings();
    }
}


